package com.rraj.common.fuse;

import com.rraj.common.cache.Cache;
import com.rraj.common.cache.CacheParam;
import com.rraj.common.page.Page;
import com.rraj.common.redis.dataRedis.RedisClient;
import com.rraj.common.utils.CollectionUtils;
import org.apache.commons.beanutils.MethodUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * Created by hqm on 2017/6/19.
 * 熔断器模式切面
 */
@Component
@Aspect
public class FuseAspect {


    @Resource
    private RedisClient redisClient;

    private ConcurrentHashMap concurrentHashMap = new ConcurrentHashMap();

    private static final Integer FUSE_NUM=5;

    @Pointcut("@annotation(com.rraj.common.fuse.Fuse)")
    public void fuseCheck() {
    }

    @Around(value = "fuseCheck() && @annotation(fuse)")
    public Object doAround(ProceedingJoinPoint joinPoint, Fuse fuse) {
        try {
            String fuseKey=fuse.fuseKey();
            if(fuse.timeout()==0){
                Object o=joinPoint.proceed();
                redisClient.del(fuseKey);
                return o;
            }else {
                Object fuseValue = redisClient.get(fuseKey);
                if (fuseValue == null) {
                    Object o = joinPoint.proceed();
                    if(isFuse(o)) {
                        redisClient.set(fuseKey, "第三方接口异常", fuse.timeout());
                    }
                    return o;
                }
                return fuseValue;
            }
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return null;
    }

    private Boolean isFuse(Object object){

        if(object==null&&!CollectionUtils.isNotEmpty(concurrentHashMap)){
            concurrentHashMap.put("num",1);
        }
        if(object==null&&CollectionUtils.isNotEmpty(concurrentHashMap)){
            Integer num = Integer.valueOf(concurrentHashMap.get("num").toString());
            concurrentHashMap.put("num",num+1);
            if(num+1>FUSE_NUM){
                concurrentHashMap.clear();
                return Boolean.TRUE;
            }
        }
        return Boolean.FALSE;

    }
}
